package net.wicp.tams.common.binlog.self;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.BitSet;

/***
 * 
 * @author zhoujunhui
 *
 */
public class LogBuffer {
	protected byte[] buffer;
	protected int origin;
	protected int limit;
	protected int position;

	public static final BigInteger BIGINT_MAX_VALUE = new BigInteger("18446744073709551615");
	public static final long NULL_LENGTH = -1L;
	public static final String ISO_8859_1 = "ISO-8859-1";
	public static final int DIG_PER_DEC1 = 9;
	public static final int DIG_BASE = 1000000000;
	public static final int DIG_MAX = 999999999;
	public static final int[] dig2bytes = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 };
	public static final int[] powers10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
	public static final int DIG_PER_INT32 = 9;
	public static final int SIZE_OF_INT32 = 4;

	protected LogBuffer() {
	}

	public LogBuffer(byte[] buffer, int origin, int limit) {
		if (origin + limit > buffer.length) {
			throw new IllegalArgumentException("capacity excceed: " + (origin + limit));
		}
		this.buffer = buffer;
		this.origin = origin;
		this.position = origin;
		this.limit = limit;
	}

	public final LogBuffer duplicate(int pos, int len) {
		if (pos + len > this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (pos + len));
		}

		int off = this.origin + pos;
		byte[] buf = Arrays.copyOfRange(this.buffer, off, off + len);
		return new LogBuffer(buf, 0, len);
	}

	public final LogBuffer duplicate(int len) {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}

		int end = this.position + len;
		byte[] buf = Arrays.copyOfRange(this.buffer, this.position, end);
		LogBuffer dupBuffer = new LogBuffer(buf, 0, len);
		this.position = end;
		return dupBuffer;
	}

	public final LogBuffer duplicate() {
		byte[] buf = Arrays.copyOfRange(this.buffer, this.origin, this.origin + this.limit);
		return new LogBuffer(buf, 0, this.limit);
	}

	public final int capacity() {
		return this.buffer.length;
	}

	public final int position() {
		return this.position - this.origin;
	}

	public final LogBuffer position(int newPosition) {
		if ((newPosition > this.limit) || (newPosition < 0)) {
			throw new IllegalArgumentException("limit excceed: " + newPosition);
		}
		this.position = (this.origin + newPosition);
		return this;
	}

	public final LogBuffer forward(int len) {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}
		this.position += len;
		return this;
	}

	public final LogBuffer consume(int len) {
		if (this.limit > len) {
			this.limit -= len;
			this.origin += len;
			this.position = this.origin;
			return this;
		}
		if (this.limit == len) {
			this.limit = 0;
			this.origin = 0;
			this.position = 0;
			return this;
		}

		throw new IllegalArgumentException("limit excceed: " + len);
	}

	public final LogBuffer rewind() {
		this.position = this.origin;
		return this;
	}

	public final int limit() {
		return this.limit;
	}

	public final LogBuffer limit(int newLimit) {
		if ((this.origin + newLimit > this.buffer.length) || (newLimit < 0)) {
			throw new IllegalArgumentException("capacity excceed: " + (this.origin + newLimit));
		}
		this.limit = newLimit;
		return this;
	}

	public final int remaining() {
		return this.limit + this.origin - this.position;
	}

	public final boolean hasRemaining() {
		return this.position < this.limit + this.origin;
	}

	public final int getInt8(int pos) {
		if ((pos >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + pos);
		}
		return this.buffer[(this.origin + pos)];
	}

	public final int getInt8() {
		if (this.position >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin));
		}
		return this.buffer[(this.position++)];
	}

	public final int getUint8(int pos) {
		if ((pos >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + pos);
		}
		return 0xFF & this.buffer[(this.origin + pos)];
	}

	public final int getUint8() {
		if (this.position >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin));
		}
		return 0xFF & this.buffer[(this.position++)];
	}

	public final int getInt16(int pos) {
		int position = this.origin + pos;

		if ((pos + 1 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | buf[(position + 1)] << 8;
	}

	public final int getInt16() {
		if (this.position + 1 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | buf[(this.position++)] << 8;
	}

	public final int getUint16(int pos) {
		int position = this.origin + pos;

		if ((pos + 1 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8;
	}

	public final int getUint16() {
		if (this.position + 1 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8;
	}

	public final int getBeInt16(int pos) {
		int position = this.origin + pos;

		if ((pos + 1 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 1)] | buf[position] << 8;
	}

	public final int getBeInt16() {
		if (this.position + 1 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 1));
		}
		byte[] buf = this.buffer;
		return buf[(this.position++)] << 8 | 0xFF & buf[(this.position++)];
	}

	public final int getBeUint16(int pos) {
		int position = this.origin + pos;

		if ((pos + 1 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 1));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 1)] | (0xFF & buf[position]) << 8;
	}

	public final int getBeUint16() {
		if (this.position + 1 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 1));
		}
		byte[] buf = this.buffer;
		return (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final int getInt24(int pos) {
		int position = this.origin + pos;

		if ((pos + 2 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | buf[(position + 2)] << 16;
	}

	public final int getInt24() {
		if (this.position + 2 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8 | buf[(this.position++)] << 16;
	}

	public final int getBeInt24(int pos) {
		int position = this.origin + pos;

		if ((pos + 2 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 2)] | (0xFF & buf[(position + 1)]) << 8 | buf[position] << 16;
	}

	public final int getBeInt24() {
		if (this.position + 2 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 2));
		}
		byte[] buf = this.buffer;
		return buf[(this.position++)] << 16 | (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final int getUint24(int pos) {
		int position = this.origin + pos;

		if ((pos + 2 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16;
	}

	public final int getUint24() {
		if (this.position + 2 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16;
	}

	public final int getBeUint24(int pos) {
		int position = this.origin + pos;

		if ((pos + 2 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 2));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 2)] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[position]) << 16;
	}

	public final int getBeUint24() {
		if (this.position + 2 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 2));
		}
		byte[] buf = this.buffer;
		return (0xFF & buf[(this.position++)]) << 16 | (0xFF & buf[(this.position++)]) << 8
				| 0xFF & buf[(this.position++)];
	}

	public final int getInt32(int pos) {
		int position = this.origin + pos;

		if ((pos + 3 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 3));
		}
		byte[] buf = this.buffer;
		return (int) (0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) buf[(position + 3)] << 24);
	}

	public final int getBeInt32(int pos) {
		int position = this.origin + pos;

		if ((pos + 3 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 3));
		}
		byte[] buf = this.buffer;
		return (int) (0xFF & buf[(position + 3)] | (0xFF & buf[(position + 2)]) << 8
				| (0xFF & buf[(position + 1)]) << 16 | (long) buf[position] << 24);
	}

	public final int getInt32() {
		if (this.position + 3 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 3));
		}
		byte[] buf = this.buffer;
		return (int) (0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16 | (long) buf[(this.position++)] << 24);
	}

	public final int getBeInt32() {
		if (this.position + 3 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 3));
		}
		byte[] buf = this.buffer;
		return (int) ((long) buf[(this.position++)] << 24 | (0xFF & buf[(this.position++)]) << 16
				| (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)]);
	}

	public final long getUint32(int pos) {
		int position = this.origin + pos;

		if ((pos + 3 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 3));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) (0xFF & buf[(position + 3)]) << 24;
	}

	public final long getBeUint32(int pos) {
		int position = this.origin + pos;

		if ((pos + 3 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 3));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 3)] | (0xFF & buf[(position + 2)]) << 8 | (0xFF & buf[(position + 1)]) << 16
				| (long) (0xFF & buf[position]) << 24;
	}

	public final long getUint32() {
		if (this.position + 3 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 3));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16 | (long) (0xFF & buf[(this.position++)]) << 24;
	}

	public final long getBeUint32() {
		if (this.position + 3 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 3));
		}
		byte[] buf = this.buffer;
		return (long) (0xFF & buf[(this.position++)]) << 24 | (0xFF & buf[(this.position++)]) << 16
				| (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final long getBeUlong40(int pos) {
		int position = this.origin + pos;

		if ((pos + 4 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 4));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 4)] | (0xFF & buf[(position + 3)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) (0xFF & buf[(position + 1)]) << 24 | (long) (0xFF & buf[position]) << 32;
	}

	public final long getBeUlong40() {
		if (this.position + 4 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 4));
		}
		byte[] buf = this.buffer;
		return (long) (0xFF & buf[(this.position++)]) << 32 | (long) (0xFF & buf[(this.position++)]) << 24
				| (0xFF & buf[(this.position++)]) << 16 | (0xFF & buf[(this.position++)]) << 8
				| 0xFF & buf[(this.position++)];
	}

	/***
	 * 读大字端数
	 * 
	 * @param len
	 * @return
	 * @author zhoujunhui
	 */
	public long readLongB(int len) {
		return readLong(len, false);
	}

	/***
	 * 读小字端数
	 * 
	 * @param len
	 * @author zhoujunhui
	 * @return
	 */
	public long readLongL(int len) {
		return readLong(len, true);
	}

	/***
	 * 读字节通用方法
	 * 
	 * @param len
	 * @param littleEndian
	 * @author zhoujunhui
	 * @return
	 */
	public long readLong(int len, boolean littleEndian) {
		long r = 0;
		for (int i = 0; i < len; ++i) {
			final long v = (0xFF & this.buffer[(this.position++)]);
			if (littleEndian) {
				r |= (v << (i << 3));
			} else {
				r = (r << 8) | v;
			}
		}
		return r;
	}

	public final long getLong48(int pos) {
		int position = this.origin + pos;

		if ((pos + 5 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) (0xFF & buf[(position + 3)]) << 24 | (long) (0xFF & buf[(position + 4)]) << 32
				| (long) buf[(position + 5)] << 40;
	}

	public final long getBeLong48(int pos) {
		int position = this.origin + pos;

		if ((pos + 5 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 5)] | (0xFF & buf[(position + 4)]) << 8 | (0xFF & buf[(position + 3)]) << 16
				| (long) (0xFF & buf[(position + 2)]) << 24 | (long) (0xFF & buf[(position + 1)]) << 32
				| (long) buf[position] << 40;
	}

	public final long getLong48() {
		if (this.position + 5 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16 | (long) (0xFF & buf[(this.position++)]) << 24
				| (long) (0xFF & buf[(this.position++)]) << 32 | (long) buf[(this.position++)] << 40;
	}

	public final long getBeLong48() {
		if (this.position + 5 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 5));
		}
		byte[] buf = this.buffer;
		return (long) buf[(this.position++)] << 40 | (long) (0xFF & buf[(this.position++)]) << 32
				| (long) (0xFF & buf[(this.position++)]) << 24 | (0xFF & buf[(this.position++)]) << 16
				| (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final long getUlong48(int pos) {
		int position = this.origin + pos;

		if ((pos + 5 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) (0xFF & buf[(position + 3)]) << 24 | (long) (0xFF & buf[(position + 4)]) << 32
				| (long) (0xFF & buf[(position + 5)]) << 40;
	}

	public final long getBeUlong48(int pos) {
		int position = this.origin + pos;

		if ((pos + 5 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 5)] | (0xFF & buf[(position + 4)]) << 8 | (0xFF & buf[(position + 3)]) << 16
				| (long) (0xFF & buf[(position + 2)]) << 24 | (long) (0xFF & buf[(position + 1)]) << 32
				| (long) (0xFF & buf[position]) << 40;
	}

	public final long getUlong48() {
		if (this.position + 5 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 5));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16 | (long) (0xFF & buf[(this.position++)]) << 24
				| (long) (0xFF & buf[(this.position++)]) << 32 | (long) (0xFF & buf[(this.position++)]) << 40;
	}

	public final long getBeUlong48() {
		if (this.position + 5 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 5));
		}
		byte[] buf = this.buffer;
		return (long) (0xFF & buf[(this.position++)]) << 40 | (long) (0xFF & buf[(this.position++)]) << 32
				| (long) (0xFF & buf[(this.position++)]) << 24 | (0xFF & buf[(this.position++)]) << 16
				| (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final long getBeUlong56(int pos) {
		int position = this.origin + pos;

		if ((pos + 6 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 6));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 6)] | (0xFF & buf[(position + 5)]) << 8 | (0xFF & buf[(position + 4)]) << 16
				| (long) (0xFF & buf[(position + 3)]) << 24 | (long) (0xFF & buf[(position + 2)]) << 32
				| (long) (0xFF & buf[(position + 1)]) << 40 | (long) (0xFF & buf[position]) << 48;
	}

	public final long getBeUlong56() {
		if (this.position + 6 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 6));
		}
		byte[] buf = this.buffer;
		return (long) (0xFF & buf[(this.position++)]) << 48 | (long) (0xFF & buf[(this.position++)]) << 40
				| (long) (0xFF & buf[(this.position++)]) << 32 | (long) (0xFF & buf[(this.position++)]) << 24
				| (0xFF & buf[(this.position++)]) << 16 | (0xFF & buf[(this.position++)]) << 8
				| 0xFF & buf[(this.position++)];
	}

	public final long getLong64(int pos) {
		int position = this.origin + pos;

		if ((pos + 7 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 7));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[position] | (0xFF & buf[(position + 1)]) << 8 | (0xFF & buf[(position + 2)]) << 16
				| (long) (0xFF & buf[(position + 3)]) << 24 | (long) (0xFF & buf[(position + 4)]) << 32
				| (long) (0xFF & buf[(position + 5)]) << 40 | (long) (0xFF & buf[(position + 6)]) << 48
				| (long) buf[(position + 7)] << 56;
	}

	public final long getBeLong64(int pos) {
		int position = this.origin + pos;

		if ((pos + 7 >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + 7));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(position + 7)] | (0xFF & buf[(position + 6)]) << 8 | (0xFF & buf[(position + 5)]) << 16
				| (long) (0xFF & buf[(position + 4)]) << 24 | (long) (0xFF & buf[(position + 3)]) << 32
				| (long) (0xFF & buf[(position + 2)]) << 40 | (long) (0xFF & buf[(position + 1)]) << 48
				| (long) buf[position] << 56;
	}

	public final long getLong64() {
		if (this.position + 7 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 7));
		}
		byte[] buf = this.buffer;
		return 0xFF & buf[(this.position++)] | (0xFF & buf[(this.position++)]) << 8
				| (0xFF & buf[(this.position++)]) << 16 | (long) (0xFF & buf[(this.position++)]) << 24
				| (long) (0xFF & buf[(this.position++)]) << 32 | (long) (0xFF & buf[(this.position++)]) << 40
				| (long) (0xFF & buf[(this.position++)]) << 48 | (long) buf[(this.position++)] << 56;
	}

	public final long getBeLong64() {
		if (this.position + 7 >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position - this.origin + 7));
		}
		byte[] buf = this.buffer;
		return (long) buf[(this.position++)] << 56 | (long) (0xFF & buf[(this.position++)]) << 48
				| (long) (0xFF & buf[(this.position++)]) << 40 | (long) (0xFF & buf[(this.position++)]) << 32
				| (long) (0xFF & buf[(this.position++)]) << 24 | (0xFF & buf[(this.position++)]) << 16
				| (0xFF & buf[(this.position++)]) << 8 | 0xFF & buf[(this.position++)];
	}

	public final BigInteger getUlong64(int pos) {
		long long64 = getLong64(pos);

		return (long64 >= 0L) ? BigInteger.valueOf(long64) : BIGINT_MAX_VALUE.add(BigInteger.valueOf(1L + long64));
	}

	public final BigInteger getBeUlong64(int pos) {
		long long64 = getBeLong64(pos);

		return (long64 >= 0L) ? BigInteger.valueOf(long64) : BIGINT_MAX_VALUE.add(BigInteger.valueOf(1L + long64));
	}

	public final BigInteger getUlong64() {
		long long64 = getLong64();

		return (long64 >= 0L) ? BigInteger.valueOf(long64) : BIGINT_MAX_VALUE.add(BigInteger.valueOf(1L + long64));
	}

	public final BigInteger getBeUlong64() {
		long long64 = getBeLong64();

		return (long64 >= 0L) ? BigInteger.valueOf(long64) : BIGINT_MAX_VALUE.add(BigInteger.valueOf(1L + long64));
	}

	public final float getFloat32(int pos) {
		return Float.intBitsToFloat(getInt32(pos));
	}

	public final float getFloat32() {
		return Float.intBitsToFloat(getInt32());
	}

	public final double getDouble64(int pos) {
		return Double.longBitsToDouble(getLong64(pos));
	}

	public final double getDouble64() {
		return Double.longBitsToDouble(getLong64());
	}

	public final long getPackedLong(int pos) {
		int lead = getUint8(pos);
		if (lead < 251) {
			return lead;
		}
		switch (lead) {
		case 251:
			return -1L;
		case 252:
			return getUint16(pos + 1);
		case 253:
			return getUint24(pos + 1);
		}
		return getUint32(pos + 1);
	}

	public final long getPackedLong() {
		int lead = getUint8();
		if (lead < 251) {
			return lead;
		}
		switch (lead) {
		case 251:
			return -1L;
		case 252:
			return getUint16();
		case 253:
			return getUint24();
		}
		long value = getUint32();
		this.position += 4;
		return value;
	}

	public final String getFixString(int pos, int len) {
		return getFixString(pos, len, "ISO-8859-1");
	}

	public final String getFixString(int len) {
		return getFixString(len, "ISO-8859-1");
	}

	public final String getFixString(int pos, int len, String charsetName) {
		if ((pos + len > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + len));
		}

		int from = this.origin + pos;
		int end = from + len;
		byte[] buf = this.buffer;
		int found = from;
		for (; (found < end) && (buf[found] != 0); ++found)
			;
		try {
			return new String(buf, from, found - from, charsetName);
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	public final String getFixString(int len, String charsetName) {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}

		int from = this.position;
		int end = from + len;
		byte[] buf = this.buffer;
		int found = from;
		for (; (found < end) && (buf[found] != 0); ++found)
			;
		try {
			String string = new String(buf, from, found - from, charsetName);
			this.position += len;
			return string;
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	public final String getFullString(int pos, int len, String charsetName) {
		if ((pos + len > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + len));
		}
		try {
			return new String(this.buffer, this.origin + pos, len, charsetName);
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	public final String getFullString(int len, String charsetName) {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}
		try {
			String string = new String(this.buffer, this.position, len, charsetName);
			this.position += len;
			return string;
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	public final String getString(int pos) {
		return getString(pos, "ISO-8859-1");
	}

	public final String getString() {
		return getString("ISO-8859-1");
	}

	/***
	 * 得到00结束的字符串
	 * 
	 * @param charsetName
	 * @author zhoujunhui
	 * @return
	 */
	public String getStringEndNull(String charsetName) {
		// byte[] allbyte = new byte[128];// 大多数128就够了
		int pos = this.position;
		int i = 0;
		while (true) {
			final byte v = this.buffer[(this.position++)];
			if (v == 0x00)
				break;
			i++;
		}
		this.position = pos;
		String retstr = getFullString(i, charsetName);
		this.position++;
		return retstr;// ByteUtil.readString(allbyte);
	}

	/***
	 * 读剩余字数
	 * 
	 * @param charsetName
	 * @author zhoujunhui
	 * @return
	 */
	public String getStringEndRest(String charsetName) {
		return getFullString(remaining(), charsetName);
	}

	/***
	 * 得到packlong的字符串
	 * 
	 * @param charsetName
	 * @author zhoujunhui
	 * @return
	 */
	public String getStringPackLong(String charsetName) {
		int len = (int) getPackedLong();
		return getFullString(len, charsetName);
	}

	public final String getString(int pos, String charsetName) {
		if ((pos >= this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + pos);
		}
		byte[] buf = this.buffer;
		int len = 0xFF & buf[(this.origin + pos)];
		if (pos + len + 1 > this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (pos + len + 1));
		}
		try {
			return new String(buf, this.origin + pos + 1, len, charsetName);
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	public final String getString(String charsetName) {
		if (this.position >= this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + this.position);
		}
		byte[] buf = this.buffer;
		int len = 0xFF & buf[this.position];
		if (this.position + len + 1 > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len + 1 - this.origin));
		}
		try {
			String string = new String(buf, this.position + 1, len, charsetName);
			this.position += len + 1;
			return string;
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException("Unsupported encoding: " + charsetName, e);
		}
	}

	private static final int getInt16BE(byte[] buffer, int pos) {
		return buffer[pos] << 8 | 0xFF & buffer[(pos + 1)];
	}

	private static final int getInt24BE(byte[] buffer, int pos) {
		return buffer[pos] << 16 | (0xFF & buffer[(pos + 1)]) << 8 | 0xFF & buffer[(pos + 2)];
	}

	private static final int getInt32BE(byte[] buffer, int pos) {
		return buffer[pos] << 24 | (0xFF & buffer[(pos + 1)]) << 16 | (0xFF & buffer[(pos + 2)]) << 8
				| 0xFF & buffer[(pos + 3)];
	}

	public final BigDecimal getDecimal(int pos, int precision, int scale) {
		int intg = precision - scale;
		int frac = scale;
		int intg0 = intg / 9;
		int frac0 = frac / 9;
		int intg0x = intg - intg0 * 9;
		int frac0x = frac - frac0 * 9;

		int binSize = intg0 * 4 + dig2bytes[intg0x] + frac0 * 4 + dig2bytes[frac0x];
		if ((pos + binSize > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + ((pos < 0) ? pos : pos + binSize));
		}
		return getDecimal0(this.origin + pos, intg, frac, intg0, frac0, intg0x, frac0x);
	}

	public final BigDecimal getDecimal(int precision, int scale) {
		int intg = precision - scale;
		int frac = scale;
		int intg0 = intg / 9;
		int frac0 = frac / 9;
		int intg0x = intg - intg0 * 9;
		int frac0x = frac - frac0 * 9;

		int binSize = intg0 * 4 + dig2bytes[intg0x] + frac0 * 4 + dig2bytes[frac0x];
		if (this.position + binSize > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + binSize - this.origin));
		}

		BigDecimal decimal = getDecimal0(this.position, intg, frac, intg0, frac0, intg0x, frac0x);
		this.position += binSize;
		return decimal;
	}

	private final BigDecimal getDecimal0(int begin, int intg, int frac, int intg0, int frac0, int intg0x, int frac0x) {
		int mask = ((this.buffer[begin] & 0x80) == 128) ? 0 : -1;
		int from = begin;

		int len = ((mask != 0) ? 1 : 0) + ((intg != 0) ? intg : 1) + ((frac != 0) ? 1 : 0) + frac;
		char[] buf = new char[len];
		int pos = 0;

		if (mask != 0) {
			buf[(pos++)] = '-';
		}
		byte[] d_copy = this.buffer;
		int tmp93_92 = begin;
		byte[] tmp93_90 = d_copy;
		tmp93_90[tmp93_92] = (byte) (tmp93_90[tmp93_92] ^ 0x80);
		int mark = pos;

		if (intg0x != 0) {
			int i = dig2bytes[intg0x];
			int x = 0;
			switch (i) {
			case 1:
				x = d_copy[from];
				break;
			case 2:
				x = getInt16BE(d_copy, from);
				break;
			case 3:
				x = getInt24BE(d_copy, from);
				break;
			case 4:
				x = getInt32BE(d_copy, from);
			}

			from = from + i;
			x ^= mask;
			if ((x < 0) || (x >= powers10[(intg0x + 1)])) {
				throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + powers10[(intg0x + 1)]);
			}
			if (x != 0) {
				for (int j = intg0x; j > 0; --j) {
					int divisor = powers10[(j - 1)];
					int y = x / divisor;
					if ((mark < pos) || (y != 0)) {
						buf[(pos++)] = (char) (48 + y);
					}
					x -= y * divisor;
				}
			}
		}

		for (int stop = from + intg0 * 4; from < stop; from += 4) {
			int x = getInt32BE(d_copy, from);
			x ^= mask;
			if ((x < 0) || (x > 999999999)) {
				throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + 999999999);
			}
			if (x != 0) {
				if (mark < pos) {
					for (int i = 9; i > 0; --i) {
						int divisor = powers10[(i - 1)];
						int y = x / divisor;
						buf[(pos++)] = (char) (48 + y);
						x -= y * divisor;
					}

				} else
					for (int i = 9; i > 0; --i) {
						int divisor = powers10[(i - 1)];
						int y = x / divisor;
						if ((mark < pos) || (y != 0)) {
							buf[(pos++)] = (char) (48 + y);
						}
						x -= y * divisor;
					}
			} else {
				if (mark >= pos)
					continue;
				for (int i = 9; i > 0; --i) {
					buf[(pos++)] = '0';
				}
			}
		}
		if (mark == pos) {
			buf[(pos++)] = '0';
		}
		if (frac > 0) {
			buf[(pos++)] = '.';
			mark = pos;

			for (int stop = from + frac0 * 4; from < stop; from += 4) {
				int x = getInt32BE(d_copy, from);
				x ^= mask;
				if ((x < 0) || (x > 999999999)) {
					throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + 999999999);
				}
				if (x != 0) {
					for (int i = 9; i > 0; --i) {
						int divisor = powers10[(i - 1)];
						int y = x / divisor;
						buf[(pos++)] = (char) (48 + y);
						x -= y * divisor;
					}

				} else {
					for (int i = 9; i > 0; --i) {
						buf[(pos++)] = '0';
					}
				}
			}
			if (frac0x != 0) {
				int i = dig2bytes[frac0x];
				int x = 0;
				switch (i) {
				case 1:
					x = d_copy[from];
					break;
				case 2:
					x = getInt16BE(d_copy, from);
					break;
				case 3:
					x = getInt24BE(d_copy, from);
					break;
				case 4:
					x = getInt32BE(d_copy, from);
				}

				x = x ^ mask;
				if (x != 0) {
					int dig = 9 - frac0x;
					x *= powers10[dig];
					if ((x < 0) || (x > 999999999)) {
						throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + 999999999);
					}
					for (int j = 9; j > dig; --j) {
						int divisor = powers10[(j - 1)];
						int y = x / divisor;
						buf[(pos++)] = (char) (48 + y);
						x -= y * divisor;
					}
				}
			}

			if (mark == pos) {
				buf[(pos++)] = '0';
			}
		}
		int tmp1064_1063 = begin;
		byte[] tmp1064_1061 = d_copy;
		tmp1064_1061[tmp1064_1063] = (byte) (tmp1064_1061[tmp1064_1063] ^ 0x80);
		String decimal = String.valueOf(buf, 0, pos);
		return new BigDecimal(decimal);
	}

	public final void fillBitmap(BitSet bitmap, int pos, int len) {
		if ((pos + (len + 7) / 8 > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + (pos + (len + 7) / 8));
		}
		fillBitmap0(bitmap, this.origin + pos, len);
	}

	public final void fillBitmap(BitSet bitmap, int len) {
		if (this.position + (len + 7) / 8 > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + (len + 7) / 8 - this.origin));
		}
		this.position = fillBitmap0(bitmap, this.position, len);
	}

	private final int fillBitmap0(BitSet bitmap, int pos, int len) {
		byte[] buf = this.buffer;

		for (int bit = 0; bit < len; bit += 8) {
			int flag = buf[(pos++)] & 0xFF;
			if (flag == 0)
				continue;
			if ((flag & 0x1) != 0)
				bitmap.set(bit);
			if ((flag & 0x2) != 0)
				bitmap.set(bit + 1);
			if ((flag & 0x4) != 0)
				bitmap.set(bit + 2);
			if ((flag & 0x8) != 0)
				bitmap.set(bit + 3);
			if ((flag & 0x10) != 0)
				bitmap.set(bit + 4);
			if ((flag & 0x20) != 0)
				bitmap.set(bit + 5);
			if ((flag & 0x40) != 0)
				bitmap.set(bit + 6);
			if ((flag & 0x80) != 0)
				bitmap.set(bit + 7);
		}
		return pos;
	}

	public final BitSet getBitmap(int pos, int len) {
		BitSet bitmap = new BitSet(len);
		fillBitmap(bitmap, pos, len);
		return bitmap;
	}

	public final BitSet getBitmap(int len) {
		BitSet bitmap = new BitSet(len);
		fillBitmap(bitmap, len);
		return bitmap;
	}

	public final void fillOutput(OutputStream out, int pos, int len) throws IOException {
		if ((pos + len > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + (pos + len));
		}
		out.write(this.buffer, this.origin + pos, len);
	}

	public final void fillOutput(OutputStream out, int len) throws IOException {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}
		out.write(this.buffer, this.position, len);
		this.position += len;
	}

	public final void fillBytes(int pos, byte[] dest, int destPos, int len) {
		if ((pos + len > this.limit) || (pos < 0)) {
			throw new IllegalArgumentException("limit excceed: " + (pos + len));
		}
		System.arraycopy(this.buffer, this.origin + pos, dest, destPos, len);
	}

	public final void fillBytes(byte[] dest, int destPos, int len) {
		if (this.position + len > this.origin + this.limit) {
			throw new IllegalArgumentException("limit excceed: " + (this.position + len - this.origin));
		}
		System.arraycopy(this.buffer, this.position, dest, destPos, len);
		this.position += len;
	}

	public final byte[] getData(int pos, int len) {
		byte[] buf = new byte[len];
		fillBytes(pos, buf, 0, len);
		return buf;
	}

	public final byte[] getData(int len) {
		byte[] buf = new byte[len];
		fillBytes(buf, 0, len);
		return buf;
	}

	public final byte[] getData() {
		return getData(0, this.limit);
	}

	public final String hexdump(int pos) {
		if (this.limit - pos > 0) {
			int begin = this.origin + pos;
			int end = this.origin + this.limit;

			byte[] buf = this.buffer;
			StringBuilder dump = new StringBuilder();
			dump.append(Integer.toHexString(buf[begin] >> 4));
			dump.append(Integer.toHexString(buf[begin] & 0xF));
			for (int i = begin + 1; i < end; ++i) {
				dump.append("_");
				dump.append(Integer.toHexString(buf[i] >> 4));
				dump.append(Integer.toHexString(buf[i] & 0xF));
			}

			return dump.toString();
		}
		return "";
	}

	public final String hexdump(int pos, int len) {
		if (this.limit - pos > 0) {
			int begin = this.origin + pos;
			int end = Math.min(begin + len, this.origin + this.limit);

			byte[] buf = this.buffer;
			StringBuilder dump = new StringBuilder();
			dump.append(Integer.toHexString(buf[begin] >> 4));
			dump.append(Integer.toHexString(buf[begin] & 0xF));
			for (int i = begin + 1; i < end; ++i) {
				dump.append("_");
				dump.append(Integer.toHexString(buf[i] >> 4));
				dump.append(Integer.toHexString(buf[i] & 0xF));
			}

			return dump.toString();
		}
		return "";
	}

}
